package com.kymatrix.mpo.plus.bpm.server.convert.definition;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.kymatrix.mpo.plus.bpm.server.flowable.entity.ModelMetaInfoEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmCategoryEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmFormEntity;
import com.kymatrix.mpo.plus.bpm.server.model.form.model.PageQueryBpmModelResp;
import com.kymatrix.mpo.plus.bpm.server.model.form.model.SaveBpmModelReq;
import com.kymatrix.mpo.plus.bpm.server.model.form.model.UpdateBpmModelReq;
import com.kymatrix.mpo.plus.bpm.server.model.form.process.QueryBpmProcessDefinitionResp;
import com.kymatrix.mpo.plus.common.business.common.PageResp;
import com.kymatrix.mpo.plus.common.util.BeanUtils;
import com.kymatrix.mpo.plus.common.util.DateUtil;
import com.kymatrix.mpo.plus.common.util.JsonUtils;
import java.util.Map;
import java.util.Objects;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;

/**
 * 流程模型 Convert
 *
 */
public class BpmModelConvert {


    public static PageResp<PageQueryBpmModelResp> buildModelPage(PageResp<Model> pageResult,
                                                           Map<String, BpmFormEntity> formMap,
                                                           Map<String, BpmCategoryEntity> categoryMap, Map<String, Deployment> deploymentMap,
                                                           Map<String, ProcessDefinition> processDefinitionMap) {
        PageResp<PageQueryBpmModelResp> res = new PageResp<>();
        res.setTotal(pageResult.getTotal());
        for (Model model : pageResult.getList()) {
            ModelMetaInfoEntity metaInfo = buildMetaInfo(model);
            BpmFormEntity form = metaInfo != null ? formMap.get(metaInfo.getFormId()) : null;
            BpmCategoryEntity category = categoryMap.get(model.getCategory());
            Deployment deployment = model.getDeploymentId() != null ? deploymentMap.get(model.getDeploymentId()) : null;
            ProcessDefinition processDefinition = model.getDeploymentId() != null ? processDefinitionMap.get(model.getDeploymentId()) : null;
            res.getList().add(buildModel0(model, metaInfo, form, category, deployment, processDefinition));
        }
        return res;
    }

    public static PageQueryBpmModelResp buildModel(Model model,
                                             byte[] bpmnBytes) {
        ModelMetaInfoEntity metaInfo = buildMetaInfo(model);
        PageQueryBpmModelResp modelVO = buildModel0(model, metaInfo, null, null, null, null);
        if (ArrayUtil.isNotEmpty(bpmnBytes)) {
            modelVO.setBpmnXml(new String(bpmnBytes));
        }
        return modelVO;
    }

    public static PageQueryBpmModelResp buildModel0(Model model,
                                                    ModelMetaInfoEntity metaInfo, BpmFormEntity form, BpmCategoryEntity category,
                                                    Deployment deployment, ProcessDefinition processDefinition) {
        PageQueryBpmModelResp modelRespVO = new PageQueryBpmModelResp().setId(model.getId()).setName(model.getName())
                .setKey(model.getKey()).setCategory(model.getCategory())
                .setCreateTime(DateUtil.of(model.getCreateTime()));
        // Form
        if (metaInfo != null) {
            modelRespVO.setFormType(metaInfo.getFormType()).setFormId(metaInfo.getFormId())
                    .setFormCustomCreatePath(metaInfo.getFormCustomCreatePath())
                    .setFormCustomViewPath(metaInfo.getFormCustomViewPath());
            modelRespVO.setIcon(metaInfo.getIcon()).setDescription(metaInfo.getDescription());
        }
        if (form != null) {
            modelRespVO.setFormId(form.getId()).setFormName(form.getName());
        }
        // Category
        if (category != null) {
            modelRespVO.setCategoryName(category.getName());
        }
        // ProcessDefinition
        if (processDefinition != null) {
            modelRespVO.setProcessDefinition(BeanUtils.toBean(processDefinition, QueryBpmProcessDefinitionResp.class));
            modelRespVO.getProcessDefinition().setSuspensionState(processDefinition.isSuspended() ?
                    SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
            if (deployment != null) {
                modelRespVO.getProcessDefinition().setDeploymentTime(DateUtil.of(deployment.getDeploymentTime()));
            }
        }
        return modelRespVO;
    }

    public static void copyToCreateModel(Model model, SaveBpmModelReq bean) {
        model.setName(bean.getName());
        model.setKey(bean.getKey());
        model.setMetaInfo(buildMetaInfoStr(null,
                null, bean.getDescription(),
                null, null, null, null));
    }

    public static void copyToUpdateModel(Model model, UpdateBpmModelReq bean) {
        model.setName(bean.getName());
        model.setCategory(bean.getCategory());
        model.setMetaInfo(buildMetaInfoStr(buildMetaInfo(model),
                bean.getIcon(), bean.getDescription(),
                bean.getFormType(), bean.getFormId(), bean.getFormCustomCreatePath(), bean.getFormCustomViewPath()));
    }

    public static String buildMetaInfoStr(ModelMetaInfoEntity metaInfo,
                                          String icon, String description,
                                          String formType, String formId, String formCustomCreatePath, String formCustomViewPath) {
        if (metaInfo == null) {
            metaInfo = new ModelMetaInfoEntity();
        }
        // 只有非空，才进行设置，避免更新时的覆盖
        if (StrUtil.isNotEmpty(icon)) {
            metaInfo.setIcon(icon);
        }
        if (StrUtil.isNotEmpty(description)) {
            metaInfo.setDescription(description);
        }
        if (Objects.nonNull(formType)) {
            metaInfo.setFormType(formType);
            metaInfo.setFormId(formId);
            metaInfo.setFormCustomCreatePath(formCustomCreatePath);
            metaInfo.setFormCustomViewPath(formCustomViewPath);
        }
        return JsonUtils.toJsonString(metaInfo);
    }

    public static ModelMetaInfoEntity buildMetaInfo(Model model) {
        return JsonUtils.parseObject(model.getMetaInfo(), ModelMetaInfoEntity.class);
    }

}
